import { useControllableValue } from 'ahooks';
import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import './index.css';

interface CalendarProps {
  value?: Date,
  defaultValue?: Date,
  onChange?: (date: Date) => void
}

interface CalendarRef {
  getDate: () => Date,
  setDate: (date: Date) => void,
}

const InternalCalendar: React.ForwardRefRenderFunction<CalendarRef, CalendarProps> = (props, ref) => {
  const {
    value,
    defaultValue = new Date(),
    onChange,
  } = props;

  const [date, setDate] = useControllableValue(props, {
    defaultValue: new Date()
  });

  useImperativeHandle(ref, () => {
    return {
      getDate() {
        return date;
      },
      setDate(date: Date) {
        setDate(date)
      }
    }
  });

  const handlePrevMonth = () => {
    setDate(new Date(date.getFullYear(), date.getMonth() - 1, 1));
  };

  const handleNextMonth = () => {
    setDate(new Date(date.getFullYear(), date.getMonth() + 1, 1));
  };

  const monthNames = [
    '一月',
    '二月',
    '三月',
    '四月',
    '五月',
    '六月',
    '七月',
    '八月',
    '九月',
    '十月',
    '十一月',
    '十二月',
  ];

  // 上个月有几天
  const daysOfMonth = (year: number, month: number) => {
    return new Date(year, month + 1, 0).getDate();
  };

  // 获取某年某月的第一天是星期几，比如返回的是3，那么从索引0-索引1都是空的，应该填充上个月的时间
  const firstDayOfMonth = (year: number, month: number) => {
    return new Date(year, month, 1).getDay();
  };

  // 获取上个月的最后几天，填充到同一个日期上
  const getDayOfLastMonth = (currentDate: Date) => {
    const year = currentDate.getFullYear() 
    const month = currentDate.getMonth()

    // 计算当前月第一天是星期几
    const currentDay = firstDayOfMonth(year, month)
    // 计算上个月的总天数
    const lastMonth = month === 0 ? 11 : month - 1
    const lastYear = month === 0 ? year - 1 : year
    let lastDayCount = daysOfMonth(lastYear, lastMonth) // 上个月天数
    
    // 返回数据
    const lastDays:number[] = []
    for (let i = currentDay - 1; i >= 0; i--) {
        lastDays.unshift(lastDayCount--)
    }

    return lastDays
  }

  const renderDates = () => {
    // 注意类型声明
    const days: React.ReactElement[] = [];

    const daysCount = daysOfMonth(date.getFullYear(), date.getMonth());
    const currentMonth = date.getMonth()
    const lastDaysCount = getDayOfLastMonth(date)
    // 上个月还剩几天
    for (let i = 0; i < lastDaysCount.length; i++) {
        const clickHandler = () => {
            // 注意month要-1
            const curDate = new Date(date.getFullYear(), date.getMonth() - 1, lastDaysCount[i]);
            setDate(curDate);
            // onChange?.(curDate);
        }
        if(i === date.getDate() && date.getMonth() === currentMonth - 1) {
            days.push(<div key={'prev' + i} className="day selected" onClick={() => clickHandler()}>{lastDaysCount[i]}</div>)
        } else {
            days.push(<div key={'prev' + i} className="empty last-light" onClick={() => clickHandler()}>{lastDaysCount[i]}</div>)
        }
    }

    // 这个月的天数
    for (let i = 1; i <= daysCount; i++) {
      const clickHandler = () => {
        const curDate = new Date(date.getFullYear(), date.getMonth(), i);
        setDate(curDate);
        // onChange?.(curDate);
      }
      if(i === date.getDate() && currentMonth === date.getMonth()) {
        days.push(<div key={i} className="day selected" onClick={() => clickHandler()}>{i}</div>);  
      } else {
        days.push(<div key={i} className="day" onClick={() => clickHandler()}>{i}</div>);
      }
    }

    // 下个月的前几天
    let nextDayCount = 7 - days.length % 7
    for (let i = 1; i <= nextDayCount; i++) {
        const clickHandler = () => {
            // 注意month要+1
            const curDate = new Date(date.getFullYear(), date.getMonth() + 1, i);
            setDate(curDate);
            // onChange?.(curDate);
        }
        if(i === date.getDate() && date.getMonth() === currentMonth + 1) {
            days.push(<div key={'next' + i} className="day selected" onClick={() => clickHandler()}>{i}</div>)
        } else {
            days.push(<div key={'next' + i} className="empty last-light" onClick={() => clickHandler()}>{i}</div>)
        }
        
    }
    return days;
  };

  return (
    <div className="calendar">
      <div className="header">
        <button onClick={handlePrevMonth}>&lt;</button>
        <div>{date.getFullYear()}年{monthNames[date.getMonth()]}</div>
        <button onClick={handleNextMonth}>&gt;</button>
      </div>
      <div className="days">
        <div className="day">日</div>
        <div className="day">一</div>
        <div className="day">二</div>
        <div className="day">三</div>
        <div className="day">四</div>
        <div className="day">五</div>
        <div className="day">六</div>
        {renderDates()}
      </div>
    </div>
  );
}

const Calendar = React.forwardRef(InternalCalendar);

function Test() {
  const calendarRef = useRef<CalendarRef>(null);

  useEffect(() => {
    console.log(calendarRef.current?.getDate().toLocaleDateString());

    setTimeout(() => {
      calendarRef.current?.setDate(new Date(2024, 3, 1));
    }, 3000);
  }, []);

  const [date, setDate] = useState(new Date())

  return <div>
    {/* ref的使用 */}
    {/* <Calendar ref={calendarRef} defaultValue={new Date('2024-8-15')}></Calendar> */}
    
    {/* 受控 父组件使用子组件，控制他的状态 */}
    {/* <Calendar value={date} defaultValue={new Date('2023-3-1')} onChange={(newDate: Date) => {
        setDate(newDate)
    }}></Calendar> */}

    {/* 非受控 不用传递setDate 子组件内部自己控制状态了 */}
    <Calendar defaultValue={new Date('2023-3-1')} onChange={(newDate: Date) => {
    }}></Calendar>
  </div>
}
export default Test;
